package com.example.mychatroom.serviceImpl;

import com.example.mychatroom.mapper.UserMapper;
import com.example.mychatroom.model.User;
import com.example.mychatroom.serviceApi.UserService;
import com.example.mychatroom.a_utils.*;
import lombok.SneakyThrows;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.ByteArrayInputStream;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {

    public static String EmailCode = new String();

    @Autowired
    public UserMapper userMapper;

    @Autowired
    public BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private BuildUserAccount buildUserAccount;

    @Value("${EmailToken}")
    private String emailToken;

    @Autowired
    private EmailCode code;

    //获取Redis操作对象
    private static RedisTemplate redisTemplate = (RedisTemplate) GetBean.getBean("redisTemplate");

    @Override
    public boolean login(HttpServletRequest request, String account, String password,
                         ResponseBodyMessage<User> responseBodyMessage) {
        //响应状态统一给定为false-》验证通过后给定为true
        responseBodyMessage.setStatus(-1);
        //创建响应数据User
        User user = new User();
        //获取session会话
        HttpSession session = request.getSession();
       // String checkCode = (String) session.getAttribute("verifyCode");
//        if (!checkCode.equals(verifyCode)){
//            //图文验证码校验不通过
//            responseBodyMessage.setMessage("验证码有误，请重新输入");
//            responseBodyMessage.setData(user);
//            return false;
//        }
        //图文验证码校验通过，校验账号和密码
        user = userMapper.getUserByAccount(account);
        if (user == null){
            responseBodyMessage.setMessage("用户信息不存在，请检查账号后重新登录");
            responseBodyMessage.setData(user);
            return false;
        }
        //用户存在，校验密码
        boolean ret = bCryptPasswordEncoder.matches(password,user.getPassword());
        if (!ret){
            //密码校验未通过
            responseBodyMessage.setMessage("密码错误，请检查密码后重试");
            responseBodyMessage.setData(new User());
            return false;
        }
        //验证通过
        responseBodyMessage.setStatus(1);
        responseBodyMessage.setMessage("登录成功");
        responseBodyMessage.setData(user);
        //将用户信息存储在Session会话当中
        session.setAttribute(SessionKey.USERINFO_SESSION_KEY,user);
        return true;
    }

    @Override
    public void registerAccount(HttpServletRequest request, String emailID, String emailCode,
                                String passwordA, String passwordB, ResponseBodyMessage<Boolean> responseBodyMessage) {
        //因为是用户注册所以里面是没有数据的
        responseBodyMessage.setData(false);
        responseBodyMessage.setStatus(-1);
        //校验邮箱验证码一致性
        HttpSession session = request.getSession(false);
        if (session == null || session.getAttribute("emailID") == null){
            //未发送验证码
            responseBodyMessage.setMessage("请先发送邮箱验证码");
            return;
        }
        //session会话当中存储着邮箱信息
        String email = (String) session.getAttribute("emailID");
        if (!email.equals(emailID)){
            responseBodyMessage.setMessage("当前邮箱与已发送验证码的邮箱不匹配");
            return;
        }
        //判断验证码是否过期
        boolean res = redisTemplate.hasKey(email);
        if (!res){
            responseBodyMessage.setMessage("验证码已过期，请重新发送");
            return;
        }
        //校验验证码一致性
        String checkCode = (String) redisTemplate.opsForValue().get(email);
        if (checkCode != null && !checkCode.equals(emailCode)) {
            responseBodyMessage.setMessage("验证码错误");
            return;
        }
        //至此，验证码验证通过

        //开始验证注册信息
        //检查邮箱是否被使用过
        User user = userMapper.getUserByEmailId(email);
        if (user != null){
            //表示验证码被使用过
            responseBodyMessage.setMessage("邮箱已被注册过，请更换邮箱后重试");
            return;
        }
        //邮箱未被使用过，验证密码一致性
        if (!passwordA.equals(passwordB)){
            responseBodyMessage.setMessage("两次输入密码不一致，请重新输入密码");
            return;
        }
        //开始生成账号并注册
        String userAccount = buildUser(email,passwordA);
        responseBodyMessage.setMessage("注册成功，您的账号为："+userAccount+",后续请通过账号进行登录");
        responseBodyMessage.setData(true);
        //注册成功后，再删除Redis当中存储的验证码
        redisTemplate.delete(email);
    }

    private String buildUser(String email, String passwordA) {
        //生成10位数账号
        String Account = buildId();
        //生成的账号在数据库中查询，如果存在就重新生成
        //如果不存在，则说明该账号可以使用，于是就将该账号、邮箱、存储到新的用户信息当中
        User user = userMapper.getUserByAccount(Account);
        while (user != null){
            //表示账号使用过，重新生成
            Account = buildId();
            user = userMapper.getUserByAccount(Account);
        }
        //当结果集为空时，则代表该随机10位数账号可用
        //对密码进行加密
        String BC = bCryptPasswordEncoder.encode(passwordA);
        int ret = userMapper.createUser(Account,BC,email);
        return Account;
    }

    private String buildId() {
        buildUserAccount.init();
        return buildUserAccount.getPersonId();
    }

//    @Override
//    @SneakyThrows
//    public void buildCheckImage(HttpServletRequest request, HttpServletResponse response) {
//        final ImageUtil imageUtil = ImageUtil.getInstance();
//        final ByteArrayInputStream image = imageUtil.getImage();
//        //验证码图片
//        final String verifyCode = imageUtil.getStr();
//        //验证码文字
//        HttpSession session = request.getSession(true);//如果没有session，则允许创建
//        session.setAttribute("verifyCode",verifyCode);
//        response.setContentType("image/jpeg");
//
//        byte[] bytes = new byte[1024];
//        try (final ServletOutputStream out = response.getOutputStream()){
//            while (image.read(bytes) != -1){
//                out.write(bytes);
//            }
//        }
//    }

    @Override
    public ResponseBodyMessage<Boolean> sendEmailCode(HttpServletRequest request, String emailId) {
        ResponseBodyMessage responseBodyMessage = new ResponseBodyMessage();
        //判断是否发送过验证码
        HttpSession session = request.getSession(true);//允许创建
        if (session != null && session.getAttribute("emailId") != null){
            //说明发送过验证码
            String key = (String) session.getAttribute("emailId");
            //判断验证码是否过期
            Boolean ret = redisTemplate.hasKey(key);
            if (ret){
                //表示key未过期，不可以重新发送验证码
                return new ResponseBodyMessage<>(-1,"已经发送过验证码，短时间内不可以重复发送",false);
            }
            //走到这，就表示验证码过期了，继续往下走发送验证码
            //移除旧的session当中存储的信息
            session.removeAttribute("emailId");
        }
        //进行验证码发送服务
        boolean ret = sendCode(request, emailId);
        if (ret){
            //验证码发送成功，将邮箱存储在session当中，将验证码存储在Redis当中，设置120秒过期
            session.setAttribute("emailID",emailId);
            //将验证码存储在Redis当中
            String checkCode = UserServiceImpl.EmailCode;
            redisTemplate.opsForValue().set(emailId,checkCode,120, TimeUnit.SECONDS);
            //封装响应数据
            //如果我自己写的话,我可以创建一个类专门用来封装邮箱
            responseBodyMessage.setStatus(1);
            responseBodyMessage.setMessage("验证码发送成功，验证码将于120秒之后过期，请尽快完成注册~");
            responseBodyMessage.setData(true);
        }else {
            responseBodyMessage.setStatus(-1);
            responseBodyMessage.setMessage("邮箱信息有误，请检查邮箱的正确性~");
            responseBodyMessage.setData(false);
        }
        return responseBodyMessage;
    }

    private boolean sendCode(HttpServletRequest request, String emailId){

        SimpleEmail email = new SimpleEmail();
        //qq：qq邮件服务器的端口号
        email.setSslSmtpPort("465");
        //这个里面的值不能随便改,smtp是qq邮箱的服务器地址
        email.setHostName("smtp.qq.com");
        //这里是授权你能给别人发邮件
        email.setAuthentication("2740936907@qq.com", emailToken);
        email.setCharset("UTF-8");
        email.setSSLOnConnect(true);
        try {
            //设置收件人的邮箱地址
            email.addTo(emailId);
            //设置发送人的qq邮箱
            email.setFrom("2740936907@qq.com");
            //设置邮件主题
            email.setSubject("【路风华】");
            //生成六位数随机验证码
            EmailCode = buildEmailCode();
            //封装验证码信息
            email.setMsg("尊敬的用户，您好，您的邮箱验证码为：" + EmailCode  + ",您当前正在执行邮箱绑定服务，如非本人操作，请忽略此邮件~");
            email.send();
            return true;
        }catch (EmailException e){
            e.printStackTrace();
            return false;
        }
    }

    private String buildEmailCode() {
        code.init();//生成随机六位验证码
        return code.getEmailCode();
    }
}
